#include <sys/tss.h>
#include <sys/global.h>
#include <yonex/debug.h>

#define LOGK(fmt, args...)  DEBUGK(fmt, ##args)

extern pointer_t GDT_Pointer;
extern u32 TSS_Table[26];
extern selector_t TSS_Selector;

void set_tss64(u64 rsp0, u64 rsp1, u64 rsp2,
    u64 ist1, u64 ist2, u64 ist3, u64 ist4,
    u64 ist5, u64 ist6, u64 ist7)
{
    *(u64 *)(TSS_Table+1) = rsp0;
	*(u64 *)(TSS_Table+3) = rsp1;
	*(u64 *)(TSS_Table+5) = rsp2;

	*(u64 *)(TSS_Table+9) = ist1;
	*(u64 *)(TSS_Table+11) = ist2;
	*(u64 *)(TSS_Table+13) = ist3;
	*(u64 *)(TSS_Table+15) = ist4;
	*(u64 *)(TSS_Table+17) = ist5;
	*(u64 *)(TSS_Table+19) = ist6;
	*(u64 *)(TSS_Table+21) = ist7;	
}

void tss_init()
{
    LOGK("init tss\n");
    tss_descriptor_t *tss_descriptor = (tss_descriptor_t *)(GDT_Pointer.base + 64);
    // TSS in GDT index = 8 ~ 9 共16字节
    tss_descriptor->limit_low = 104 - 1; // TSS_Table共104字节
    tss_descriptor->base_low = ((u64)&TSS_Table) & 0xffffff;
    tss_descriptor->type = 0b1001;
    tss_descriptor->segment = 0;
    tss_descriptor->DPL = 0;
    tss_descriptor->present = 1;
    tss_descriptor->limit_hign = 0;
    tss_descriptor->available = 0;
    tss_descriptor->long_mode = 0;
    tss_descriptor->big = 0;
    tss_descriptor->granularity = 0;
    tss_descriptor->base_mid = (((u64)&TSS_Table)>>24) & 0xff;
    tss_descriptor->base_high = (((u64)&TSS_Table)>>32);
    tss_descriptor->reserved = 0;

    set_tss64(0x7c00, 0x7c00, 0x7c00,
    0x7c00, 0x7c00, 0x7c00, 0x7c00,
    0x7c00, 0x7c00, 0x7c00);
}
